package tr.edu.yildiz.ce.dap.apm.process;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.util.Iterator;
import java.util.Set;

import tr.edu.yildiz.ce.dap.apm.commands.DetailCommandReply;
import tr.edu.yildiz.ce.dap.apm.commands.ListCommandReply;
import tr.edu.yildiz.ce.dap.apm.commands.RegisterCommandReply;
import tr.edu.yildiz.ce.dap.apm.commands.RetrieveCommandReply;
import tr.edu.yildiz.ce.dap.apm.commands.basic.BasicReply;
import tr.edu.yildiz.ce.dap.appagent.command.deployment.base.CommandConstants;
import tr.edu.yildiz.ce.dap.appagent.model.DapMessage;
import tr.edu.yildiz.ce.dap.appagent.service.MessageConverter;

public class CommandReceiver implements Runnable{
	//ISO-8859-1
	String encoding ;
	//ConfConstants.proxy_port
	int port;
	
	public CommandReceiver(String encoding,int port) {
		this.encoding = encoding;
		this.port = port;
	}
	
	public void run() {
		try {
			replyInternal();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	protected void replyInternal() throws Exception {
		Charset charset = Charset.forName(encoding);
		CharsetEncoder encoder = charset.newEncoder();
		CharsetDecoder decoder = charset.newDecoder();

		ByteBuffer buffer = ByteBuffer.allocate(512);

		Selector selector = Selector.open();

		ServerSocketChannel server = ServerSocketChannel.open();
		server.socket().bind(new java.net.InetSocketAddress(port));
		server.configureBlocking(false);
		SelectionKey serverkey = server.register(selector,
				SelectionKey.OP_ACCEPT);

		for (;;) {
			selector.select();
			Set keys = selector.selectedKeys();

			for (Iterator i = keys.iterator(); i.hasNext();) {
				SelectionKey key = (SelectionKey) i.next();
				i.remove();

				if (key == serverkey) {
					if (key.isAcceptable()) {
						SocketChannel client = server.accept();
						client.configureBlocking(false);
						SelectionKey clientkey = client.register(selector,
								SelectionKey.OP_READ);
						clientkey.attach(new Integer(0));
					}
				} else {
					SocketChannel client = (SocketChannel) key.channel();
					if (!key.isReadable())
						continue;
					int bytesread = client.read(buffer);
					if (bytesread == -1) {
						key.cancel();
						client.close();
						continue;
					}
					buffer.flip();
					String request = decoder.decode(buffer).toString();
					DapMessage input = MessageConverter.convertToObject(request);
					DapMessage output = replyInternal(input);
					buffer.clear();
					System.out.println(MessageConverter.convertToXML(output));
					client.write(encoder.encode(CharBuffer.wrap(MessageConverter.convertToXML(output))));
					key.cancel();
					client.close();
				}
			}
		}
	}
	
	protected  DapMessage replyInternal(DapMessage input) {
		BasicReply mock  = null;
		if (input.getCommand().equals(CommandConstants.REGISTER)){
			mock = new RegisterCommandReply();
		}else if (input.getCommand().equals(CommandConstants.LIST)){
			mock = new ListCommandReply();
		}else if (input.getCommand().equals(CommandConstants.RETRIEVE)){
			mock = new RetrieveCommandReply();
		} else if (input.getCommand().equals(CommandConstants.DETAIL)){
			mock = new DetailCommandReply();
		} 
		return mock.reply(input);
	}

	
	
	
}
